#include "Util.h"


enum Endianness { Big = 0, Little = 1, Unknown = 2};
static Endianness endianness = Unknown;
union IntChar4_t_ { int i; char c[4];};

//Util::Endianness Util::endianness = Unknown;

bool Util::IsLittleEndian()
{
    switch(endianness)
    {
        case Endianness::Big:
            return false;
        case Endianness::Little:
            return true;
        case Unknown:
        default:
            IntChar4_t_ t{};
            t.i = 1;
            if(t.c[0] == 1)
            {
                endianness = Little;
                return true;
            }
            else
            {
                endianness = Big;
                return false;
            }
    }
}

void Util::Int2Char4(int i, char *c)
{
    IntChar4_t_ t{};
    t.i = i;
    if(IsLittleEndian())
    {
        c[0] = t.c[0];
        c[1] = t.c[1];
        c[2] = t.c[2];
        c[3] = t.c[3];
    }
    else
    {
        c[0] = t.c[3];
        c[1] = t.c[2];
        c[2] = t.c[1];
        c[3] = t.c[0];
    }
}

void Util::Char42Int(int &i, const char *c)
{
    IntChar4_t_ t{};
    if(IsLittleEndian())
    {
        t.c[0] = c[0];
        t.c[1] = c[1];
        t.c[2] = c[2];
        t.c[3] = c[3];
    }
    else
    {
        t.c[0] = c[3];
        t.c[1] = c[2];
        t.c[2] = c[1];
        t.c[3] = c[0];
    }
    i = t.i;
}

void Util::DrawImageOnCanvas(const cv::_OutputArray &canvas, const cv::_InputArray &image, const cv::_InputArray &alpha)
{
    for(int r = 0; r < canvas.getMat().rows; ++r)
    {
        for(int c = 0; c < canvas.getMat().cols; ++c)
        {
            canvas.getMatRef().at<cv::Vec3b>(r, c) = (canvas.getMat().at<cv::Vec3b>(r, c) * ((255.0 - (double)alpha.getMat().at<uint8_t>(r, c)) / 255.0)) + (image.getMat().at<cv::Vec3b>(r, c) * ((double)alpha.getMat().at<uint8_t>(r, c) / 255.0));
        }
    }
}

std::unique_ptr<QImage> Util::CvImage2QImage(const cv::Mat &src)
{
    static cv::Mat tmp_image;
    switch (src.channels())
    {
        case 1:
            return std::make_unique<QImage>((const uchar *) (src.data), src.cols, src.rows, src.cols, QImage::Format_Grayscale8);
        case 3:
            cv::cvtColor(src, tmp_image, cv::COLOR_BGR2RGB);
            return std::make_unique<QImage>((const uchar *) (tmp_image.data), tmp_image.cols, tmp_image.rows, tmp_image.cols * 3, QImage::Format_RGB888);
        case 4:
            cv::cvtColor(src, tmp_image, cv::COLOR_BGRA2RGBA);
            return std::make_unique<QImage>((const uchar *) (tmp_image.data), tmp_image.cols, tmp_image.rows, tmp_image.cols * 4, QImage::Format_RGBA8888);
        default:
            return std::make_unique<QImage>(reinterpret_cast<const uchar *>("\0\0\0\0"), 1, 1, QImage::Format_RGBA8888);
    }
}

